#include "znx_thread_base.h"

__thread size_t t_buf_size = 0;
__thread u_char *t_buf = NULL;
__thread size_t t_log_buf_size = 0;
__thread u_char *t_log_buf = NULL;
__thread znx_thread_base_t *current_thread_base = NULL;


void
znx_t_buf_grow(size_t size)
{
    if (t_buf_size >= size) {
        return;
    }

    if (t_buf != NULL) {
        free(t_buf);
    }

    t_buf_size = size;
    t_buf = malloc(t_buf_size);
}

void
znx_t_log_buf_grow(size_t size)
{
    if (t_log_buf_size >= size) {
        return;
    }

    if (t_log_buf != NULL) {
        free(t_log_buf);
    }

    t_log_buf_size = size;
    t_log_buf = malloc(t_log_buf_size);
}


static inline void *
znx_thread_base_runner(void *arg)
{
    void *ret = NULL;
    znx_thread_base_t    *thread_base = (znx_thread_base_t *)arg;
    current_thread_base = thread_base;
    ret = thread_base->execute_pt(thread_base);

    return ret;
}


void
znx_thread_base_start(
    const char *tag,
    znx_thread_base_t *thread_base,
    znx_thread_base_execute_pt execute_pt,
    void *data,
    size_t mem_freelists_level,
    size_t aligned_mem_freelists_level)
{
    thread_base->tag = tag;
    thread_base->execute_pt = execute_pt;
    thread_base->data = data;

    if (mem_freelists_level > 0) {
        thread_base->mem_freelists
            = znx_thread_mem_freelists_create(mem_freelists_level);
    }

    if (aligned_mem_freelists_level > 0) {
        thread_base->aligned_mem_freelists
            = znx_thread_4kaligned_mem_freelists_create(aligned_mem_freelists_level);
    }

    thread_base->tid = znx_thread_create(znx_thread_base_runner, thread_base, ZNX_FALSE);
}


void
znx_thread_base_join(znx_thread_base_t *thread_base, void **ret)
{
    znx_thread_join(thread_base->tid, ret);

    if (thread_base->mem_freelists) {
        znx_thread_mem_freelists_destroy(thread_base->mem_freelists);
    }

    if (thread_base->aligned_mem_freelists) {
        znx_thread_4kaligned_mem_freelists_destroy(thread_base->aligned_mem_freelists);
    }
}


void *
znx_thread_malloc(size_t size)
{
    znx_thread_base_t *thread_base = current_thread_base;
    if (thread_base && thread_base->mem_freelists) {
        return znx_thread_mem_freelists_alloc(thread_base->mem_freelists, size);
    }

    return znx_mem_alloc(size);
}


void
znx_thread_free(void *ptr)
{
    znx_thread_base_t *thread_base = current_thread_base;
    if (thread_base && thread_base->mem_freelists) {
        return znx_thread_mem_freelists_free(thread_base->mem_freelists, ptr);
    }

    return znx_mem_free(ptr);
}


void *
znx_thread_aligned_malloc(size_t size)
{
    znx_thread_base_t *thread_base = current_thread_base;
    if (thread_base && thread_base->aligned_mem_freelists) {
        return znx_thread_4kaligned_mem_freelists_alloc(thread_base->aligned_mem_freelists, size);
    }

    return znx_4kaligned_mem_alloc(size);
}


void znx_thread_aligned_free(void *ptr)
{
    znx_thread_base_t *thread_base = current_thread_base;
    if (thread_base && thread_base->aligned_mem_freelists) {
        return znx_thread_4kaligned_mem_freelists_free(thread_base->aligned_mem_freelists, ptr);
    }

    return znx_4kaligned_mem_free(ptr);
}
